#include <boost/interprocess/allocators/allocator.hpp>
#include <boost/interprocess/containers/map.hpp>
#include <boost/interprocess/containers/vector.hpp>
#include <boost/interprocess/managed_shared_memory.hpp>
#include <cstdlib> //std::system
#include <iostream>
#include <string>

namespace bi = boost::interprocess;

struct shm_remove {
    shm_remove() {
        bi::shared_memory_object::remove("shared_mem_segment");
    }
    ~shm_remove() {
        bi::shared_memory_object::remove("shared_mem_segment");
    }
};

class with_container {
  public:
    bi::vector<int, bi::allocator<int, bi::managed_shared_memory::segment_manager>> vec_;
    bi::map<int, double, std::less<int>,
            bi::allocator<std::pair<const int, double>, bi::managed_shared_memory::segment_manager>>
        map_;

    with_container(
        bi::allocator<int, bi::managed_shared_memory::segment_manager>&                          vec_segment_manager,
        bi::allocator<std::pair<const int, double>, bi::managed_shared_memory::segment_manager>& map_segment_manager)
            : vec_(vec_segment_manager), map_(std::less<int>(), map_segment_manager) {}
};

int main(int argc, char* argv[]) {
    if (argc == 1) {
        shm_remove remover;
        auto       seg = bi::managed_shared_memory(bi::open_or_create, "shared_mem_segment", 65536);
        auto vec_alloc = bi::allocator<int, bi::managed_shared_memory::segment_manager>(seg.get_segment_manager());
        auto map_alloc = bi::allocator<std::pair<const int, double>, bi::managed_shared_memory::segment_manager>(
            seg.get_segment_manager());
        auto class_with_container  = seg.construct<with_container>("my_class_with_vec")(vec_alloc, map_alloc);
        class_with_container->vec_ = {1, 2, 3};
        class_with_container->map_.insert_or_assign(1, 2.0);

        auto child_command_line = std::string{argv[0]};
        return std::system((child_command_line + std::string{" child "}).c_str()) == 0;
    } else {
        auto seg                  = bi::managed_shared_memory(bi::open_only, "shared_mem_segment");
        auto class_with_container = seg.find<with_container>("my_class_with_vec").first;
        for (const auto& v : class_with_container->vec_) {
            std::cout << v;
        }
        std::cout << std::endl;
        for (const auto& [i, m] : class_with_container->map_) {
            std::cout << i << " " << m << std::endl;
        }
        seg.destroy_ptr(class_with_container);
        return 0;
    }
}